import 'ol/ol.css'
//创建地图
import {
    Map,
    View
} from 'ol'
import TileLayer from 'ol/layer/Tile'
import SourceXYZ from 'ol/source/XYZ'
//添加poi
import {
    Icon,
    Style,
    Text,
    Fill,
    Stroke,
    Circle
} from "ol/style";
import {
    Vector as VectorSource,
    Cluster
} from "ol/source";
import {
    Vector as VectorLayer,
    Heatmap as HeatmapLayer
} from 'ol/layer'
import Feature from "ol/Feature";
import {
    Circle as Block_Circle,
    LineString,
    Point,
    Polygon
} from 'ol/geom';
import Overlay from 'ol/Overlay'
import Draw from 'ol/interaction/Draw';
import {createBox} from 'ol/interaction/Draw';
class Ymap {
    constructor(options) {
        this.option = options.option
        this.el = options.el
        this.tk = this.option.key
        this.ymap = null
        this.maplayers = []
        return this.initMap()
    }
    initMap() {
        this.ymap = new Map({
            target: this.el,
            layers: [
                new TileLayer({
                    source: new SourceXYZ({
                        url: 'http://t1.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=' + this.tk,
                    })
                }),
                new TileLayer({
                    source: new SourceXYZ({
                        url: 'http://t1.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=' + this.tk,
                    })
                }),
            ],
            view: new View({
                projection: "EPSG:4326",
                center: this.option.center || [116.305435, 39.965488],
                zoom: this.option.zoom || 11,
                minZoom: this.option.minZoom,
                maxZoom: this.option.maxZoom > 17 ? 17 : this.option.maxZoom
            })
        })
        this.ymapDrawEvent()
        return this.ymap
    }
    //绑定操作方法
    ymapDrawEvent() {
        this.ymap.addMaker = this.addMaker.bind(this)
        this.ymap.remove = this.remove.bind(this)
        this.ymap.removeDraw = this.removeDraw.bind
        this.ymap.removeAllMaker = this.removeAllMaker.bind(this)
        this.ymap.clearMap = this.clearMap.bind(this)
        this.ymap.getLayers = this.getLayers.bind(this)
        this.ymap.addCluster = this.addCluster.bind(this)
        this.ymap.addCircle = this.addCircle.bind(this)
        this.ymap.drawCircle = this.drawCircle.bind(this)
        this.ymap.drawRect = this.drawRect.bind(this)
        this.ymap.addLine = this.addLine.bind(this)
        this.ymap.drawLine = this.drawLine.bind(this)
        this.ymap.addPolygon = this.addPolygon.bind(this)
        this.ymap.drawPolygon = this.drawPolygon.bind(this)
        this.ymap.addSector = this.addSector.bind(this)
        this.ymap.addMakerOverlay = this.addMakerOverlay.bind(this)
        this.ymap.flyTo = this.flyTo.bind(this)
        this.ymap.addHeatMap = this.addHeatMap.bind(this)
    }
    //添加maker
    addMaker(option) {
        //创建矢量容器
        let vectorSource = new VectorSource()
        //创建图标特性
        let feature = new Feature({
            type: 'icon',
            geometry: new Point(option.location),
            name: option.name || 'maker'
        });
        vectorSource.addFeatures([feature])
        //创建矢量层
        let makerLayer = new VectorLayer({
            className: option.className || 'map-maker',
            source: vectorSource,
            style: new Style({
                image: new Icon({
                    opacity: option.opacity || 1,
                    src: option.icon || 'https://openlayers.org/en/latest/examples/data/icon.png'
                }),
                text: new Text({
                    text: option.label || null,
                    fill: new Fill({
                        color: option.textcolor || '#000',
                    }),
                    font: option.font || '14px Microsoft YaHei',
                    offsetX: option.offsetX || 0,
                    offsetY: option.offsetY || 30,
                    padding: option.padding || [2, 10, 0, 10],
                    backgroundStroke: new Stroke({
                        color: option.borderColor || 'transparent',
                        width: option.borderWidth || 1,
                    }),
                    backgroundFill: new Fill({
                        color: option.bgColor || '#fff'
                    })
                })
            }),
            zIndex: 11
        })
        this.maplayers.push(makerLayer)
        this.ymap.addLayer(makerLayer)
        return makerLayer
    }
    //删除Layer
    remove(Layer) {
        this.ymap.removeLayer(Layer);
        this.maplayers = this.maplayers.filter(item=>{
            if(Layer.ol_uid !=item.ol_uid){
                return item
            }
        })
    }
    removeDraw(draw) {
        this.ymap.removeInteraction(draw);
    }
    //删除全部maker
    removeAllMaker() {
        this.makers.forEach(Maker => {
            this.ymap.removeLayer(Maker);
        })
    }
    //清空地图
    clearMap() {
        this.maplayers.forEach(Maker => {
            this.ymap.removeLayer(Maker);
        })
        this.maplayers = []
    }
    //获取所有layer
    getLayers(){
        return this.maplayers
    }
    //添加点聚合
    addCluster(option) {
        let featureCluster = [] //聚合数组
        let styleCache = {}; //聚合群的要素样式
        console.log(option)
        option.points.forEach(point => {
            let feature = new Feature({
                type: 'icon',
                geometry: new Point(point),
                name: option.name || 'makerCluster',
                img: option.icon || 'https://openlayers.org/en/latest/examples/data/icon.png'
            })
            featureCluster.push(feature)
        })
        let makerCluster = new VectorLayer({
            className: option.className || 'map-maker-cluster',
            source: new Cluster({
                distance: option.distance || 40,
                // 矢量要素数据源
                source: new VectorSource({
                    features: featureCluster,
                }),
            }),
            style: function (feature, resolution) {
                const size = feature.get("features").length;
                let style = styleCache[size];
                let sizeRadius = 12;
                if (size > 30) {
                    sizeRadius = 12
                }
                if (size > 50) {
                    sizeRadius = 16
                }
                if (size > 100) {
                    sizeRadius = 24
                }
                if (size > 150) {
                    sizeRadius = 30
                }
                if (size > 1) {
                    if (option.bgImg) {
                        style = [
                            new Style({
                                image: new Icon({
                                    opacity: option.opacity ||1,
                                    src: option.bgImg || 'https://openlayers.org/en/latest/examples/data/icon.png'
                                }),
                                // 文本设置
                                text: new Text({
                                    text: size.toString(),
                                    fill: new Fill({
                                        color: option.fontColor || "#fff",
                                    }),
                                    font: option.font || "14px Microsoft YaHei",
                                    offsetX: option.offsetX || 0,
                                    offsetY: option.offsetY || 0
                                }),
                            }),
                        ];
                        styleCache[size] = style;
                    } else {
                        style = [
                            new Style({
                                image: new Circle({
                                    radius: sizeRadius,
                                    // 边线
                                    stroke: new Stroke({
                                        color: option.borderColor || 'transparent',
                                        width: option.borderWidth || 1,
                                    }),
                                    fill: new Fill({
                                        color: option.backgroundColor || '#3BD16C',
                                    }),
                                }),
                                // 文本设置
                                text: new Text({
                                    text: size.toString(),
                                    fill: new Fill({
                                        color: option.fontColor || "#fff",
                                    }),
                                    font: option.font || "14px Microsoft YaHei",
                                    offsetX: option.offsetX || 0,
                                    offsetY: option.offsetY || 0
                                }),
                            }),
                        ];
                        styleCache[size] = style;
                    }
                } else {
                    style = [
                        new Style({
                            image: new Icon({
                                opacity: option.opacity || 0.75,
                                src: option.icon || 'https://openlayers.org/en/latest/examples/data/icon.png'
                            }),
                            // 文本设置
                            text: new Text({
                                text: option.label || '',
                                fill: new Fill({
                                    color: option.fontColor || "#fff",
                                }),
                                font: option.font || "14px Microsoft YaHei",
                                offsetX: option.offsetX || 0,
                                offsetY: option.offsetY || 0
                            }),
                        }),
                    ];
                }
                return style
            },
            zIndex: 11
        })
        this.ymap.addLayer(makerCluster)
        this.maplayers.push(makerCluster)
        return makerCluster
    }
    //添加圆
    addCircle(option) {
        //创建矢量容器
        let metersUnit = this.ymap.getView().getProjection().getMetersPerUnit()
        console.log(metersUnit)
        let vectorSource = new VectorSource({})
        let centerRadius = new Block_Circle(option.location, (option.radius / metersUnit))

        //创建图标特性
        const circleFeature = new Feature({
            type: 'mapCircle',
            name: option.name || 'mapCircle',
            geometry: centerRadius,
        })
        //图标特性添加到矢量容器
        vectorSource.addFeature(circleFeature)
        //创建矢量图层
        let circlePolygon = new VectorLayer({
            className: option.className || 'map-circe',
            source: vectorSource,
            style: new Style({
                stroke: new Stroke({
                    color: option.borderColor || 'transparent',
                    width: option.borderWidth || 1,
                }),
                fill: new Fill({
                    color: option.backgroundColor || 'rgba(255,255,255,0.3)',
                }),
            }),
            zIndex: 20
        })
        this.ymap.addLayer(circlePolygon)
        this.maplayers.push(circlePolygon)
        return circlePolygon

    }
    //制作线
    addLine(option) {
        let vectorSource = new VectorSource({})
        const feature = new Feature({
            name: option.name || 'map-line',
            geometry: new LineString(option.points),
        });
        vectorSource.addFeature(feature)
        let lineStringLayer = new VectorLayer({
            className: option.className,
            source: vectorSource,
            zIndex: option.zIndex || 20,
            style: function (feature, resolution) {
                const style = [
                    new Style({
                        stroke: new Stroke({
                            color: option.lineColor || '#409eff',
                            width: option.lineWidth || 2,
                            lineDash: option.lineDash || null,
                            lineDashOffset: 0
                        })
                    }),
                ];
                return style;
            }
        })
        this.ymap.addLayer(lineStringLayer)
        this.maplayers.push(lineStringLayer)
        return lineStringLayer
    }
    //画线
    drawLine(option) {
        let vectorSource = new VectorSource({})
        let lineLayer = new VectorLayer({
            source: vectorSource,
            style: function (feature) {
                let geometry = feature.getGeometry();
                let styles = [
                    new Style({
                        stroke: new Stroke({
                            color: option.lineColor || '#409eff',
                            width: option.lineWidth || 2,
                            lineDash: option.lineDash || null,
                            lineDashOffset: 0
                        }),
                    })
                ];

                geometry.forEachSegment(function (start, end) {
                    var dx = end[0] - start[0];
                    var dy = end[1] - start[1];
                    var rotation = Math.atan2(dy, dx);
                    // arrows
                    styles.push(
                        new Style({
                            geometry: new Point(end),
                            image: new Icon({
                                src: option.lineIcon || 'https://openlayers.org/en/latest/examples/data/arrow.png',
                                anchor: [0.75, 0.5],
                                rotateWithView: true,
                                rotation: -rotation,
                            }),
                        })
                    )
                })
                return styles
            }
        });
        this.ymap.addLayer(lineLayer)
        this.maplayers.push(lineLayer)
        let draw = new Draw({
            source: vectorSource,
            type: 'LineString',
        })
        this.ymap.addInteraction(draw);
        return draw

    }
    //制作多边形
    addPolygon(option) {
        let vectorSource = new VectorSource({})
        // 所有点共同构成一个 feature
        const feature = new Feature({
            name: option.name || 'map-Polygon',
            geometry: new Polygon([option.points]),
        })
        vectorSource.addFeature(feature)
        let polygonLayer = new VectorLayer({
            className: option.className,
            source: vectorSource,
            zIndex: option.zIndex || 20,
            style: function (feature, resolution) {
                const style = [
                    new Style({
                        stroke: new Stroke({
                            color: option.lineColor || '#409eff',
                            width: option.lineWidth || 2,
                            lineDash: option.lineDash || null,
                            lineDashOffset: 0
                        }),
                        //填充样式
                        fill: new Fill({
                            color: option.bgColor || 'rgba(0,0,0,0.8)' //颜色、渐变或图案
                        })
                    }),
                ];
                return style;
            },
        })
        this.ymap.addLayer(polygonLayer)
        this.maplayers.push(polygonLayer)
        return polygonLayer
    }
    //绘制多边形
    drawPolygon(option) {
        let vectorSource = new VectorSource({})
        let PolygonLayer = new VectorLayer({
            source: vectorSource,
            style: function (feature) {
                let styles = [
                    new Style({
                        stroke: new Stroke({
                            color: option.lineColor || '#409eff',
                            width: option.lineWidth || 2,
                            lineDash: option.lineDash || null,
                            lineDashOffset: 0
                        }),
                        //填充样式
                        fill: new Fill({
                            color: option.backgroundColor || 'rgba(0,0,0,0.8)' //颜色、渐变或图案
                        })
                    })
                ];
                return styles
            }
        });
        this.ymap.addLayer(PolygonLayer)
        this.maplayers.push(PolygonLayer)
        let draw = new Draw({
            source: vectorSource,
            type: 'Polygon',
        })
        this.ymap.addInteraction(draw);
        return draw
    }
    //绘制圆
    drawCircle(option) {
        let vectorSource = new VectorSource({})
        let PolygonLayer = new VectorLayer({
            source: vectorSource,
            style: function (feature) {
                let styles = [
                    new Style({
                        stroke: new Stroke({
                            color: option.lineColor || '#409eff',
                            width: option.lineWidth || 2,
                            lineDash: option.lineDash || null,
                            lineDashOffset: 0
                        }),
                        //填充样式
                        fill: new Fill({
                            color: option.bgColor || 'rgba(0,0,0,0.8)' //颜色、渐变或图案
                        })
                    })
                ];
                return styles
            }
        });
        this.ymap.addLayer(PolygonLayer)
        this.maplayers.push(PolygonLayer)
        let draw = new Draw({
            source: vectorSource,
            type: 'Circle',
        })
        this.ymap.addInteraction(draw);
        return draw
    }
    //绘制矩形
    drawRect(option) {
        let vectorSource = new VectorSource({})
        let PolygonLayer = new VectorLayer({
            source: vectorSource,
            style: function (feature) {
                let styles = [
                    new Style({
                        stroke: new Stroke({
                            color: option.lineColor || '#409eff',
                            width: option.lineWidth || 2,
                            lineDash: option.lineDash || null,
                            lineDashOffset: 0
                        }),
                        //填充样式
                        fill: new Fill({
                            color: option.bgColor || 'rgba(0,0,0,0.8)' //颜色、渐变或图案
                        })
                    })
                ];
                return styles
            }
        });
        this.ymap.addLayer(PolygonLayer)
        this.maplayers.push(PolygonLayer)
        let draw = new Draw({
            source: vectorSource,
            type: 'Circle',
            geometryFunction: createBox()
        })
        this.ymap.addInteraction(draw);
        return draw
    }
    //添加overlay弹窗
    addMakerOverlay(option) {
        option.html.style.display = 'block'
        let popup = new Overlay({
            id: option.id || '',
            element: option.html || '',
            offset: option.offset || [0, 0],
            position: option.coordinate,
            positioning: option.position || 'bottom-center',
            stopEvent: true,
            className: option.className || 'map-overlay',
            autoPanAnimation: {
                duration: 250,
            },
        });
        this.ymap.addOverlay(popup);
        return popup
    }
    //跳转到指定位置
    flyTo(option) {
        let view = this.ymap.getView();
        view.animate({
            center: option.location,
            duration: option.duration || 0,
            zoom: option.zoom
        })
    }
    addSector(option) {
        let metersUnit = this.ymap.getView().getProjection().getMetersPerUnit();
        let vectorSource = new VectorSource({});
        let centerSector = this.Sectorn(
            option.location,
            option.radius / metersUnit, option.startDeg, option.moveDeg)
        //创建图标特性
        const SectorFeature = new Feature({
            type: "mapSector",
            name: "mapSector",
            geometry: centerSector,
        });

        //图标特性添加到矢量容器
        vectorSource.addFeature(SectorFeature);
        //创建矢量图层
        let SectorPolygon = new VectorLayer({
            className: "map-Sector",
            source: vectorSource,
            style: new Style({
                stroke: new Stroke({
                    color: option.borderColor || "rgba(0,255,0,0.6)",
                    width: 0,
                }),
                fill: new Fill({
                    color: option.bgColor || "rgba(9,0,0)",
                }),
            }),
            zIndex: 9,
            opacity: option.opacity || 1
        });
        this.ymap.addLayer(SectorPolygon);
        this.maplayers.push(SectorPolygon)
        return SectorPolygon
    }

    /**
     * 创建扇形
     * @param [x,y] center 扇形中心点
     * @param number randius 扇形半径 与中心点对应的坐标系单位
     * @param number sAngle 扇形起始边与X轴正方向夹角°
     * @param number angle 圆心角°（逆时针方向为正）
     * @returns {ol.geom.Polygon}
     * @constructor
     */
    Sectorn(center, randius, sAngle, angle) {
        sAngle = sAngle % 360;
        var points = [];
        points.push(center);
        for (var i = 0; i <= angle; ++i) {
            var x = center[0] + randius * Math.cos(this.degreeToRadian(sAngle + (i - 1)));
            var y = center[1] + randius * Math.sin(this.degreeToRadian(sAngle + i));
            points.push([x, y]);
        }
        points.push(center);
        return new Polygon([points]);
    }

    degreeToRadian(degree) {
        return degree * Math.PI / 180;
    }
    //添加热力图
    addHeatMap(heatData) {
        const mysource = new VectorSource();
        const features = [];
        heatData.features.forEach((item) => {
          const feature = new Feature({
            geometry: new Point(item.coordinates),
            weight: item.count,
          });
          features.push(feature);
        });
        mysource.addFeatures(features);
        let heatmap = new HeatmapLayer({
          source: mysource,
          blur: 40,
          radius: 30,
          weight: (feature) => {
            const count = Number(feature.get("weight"));
            const magnitude = count / 1;
            return magnitude;
          },
          zIndex: 200,
        });
        this.maplayers.push(heatmap)
        this.ymap.addLayer(heatmap);
        return heatmap
    }
}

export default Ymap